package com.stxx.stiot2.ws;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.stxx.stiot2.constants.Commands;
import com.stxx.stiot2.domain.Profile;
import com.stxx.stiot2.event.dto.C2pMsg;
import com.stxx.stiot2.external.RedisServer;
import com.stxx.stiot2.service.SignalService;
import com.stxx.stiot2.service.TerminalService;
import com.stxx.stiot2.ws.domain.PageMessage;
import com.stxx.stiot2.ws.domain.PageModel;
import com.stxx.stiot2.ws.domain.SocketRespone;
import com.stxx.stiot2.ws.domain.WsSession;
import com.stxx.stiot2.event.CommandListener;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.event.EventBus;
import org.noear.solon.net.annotation.ServerEndpoint;
import org.noear.solon.net.websocket.WebSocket;
import org.noear.solon.net.websocket.listener.SimpleWebSocketListener;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint("/ws/stiot/{token}")
public class WsController extends SimpleWebSocketListener {
    @Inject
    TerminalService terminalService;
    private static ConcurrentHashMap<String, WsSession> webSocketSet = new ConcurrentHashMap<>();
    @Override
    public void onMessage(WebSocket socket, String text) throws IOException {
        //socket.send("我收到了：" + text);
        String token = socket.param("token");
        WsSession wsSession = webSocketSet.get(token);
        JSONObject jsonObject = JSON.parseObject(text);

        //判断是否需要指定发送，具体规则自定义
        C2pMsg message1 = new C2pMsg();
        message1.setWsSession(wsSession);
        message1.setCommand(jsonObject.getString("command"));
        //心跳包
        if(StrUtil.equals(message1.getCommand(),"ping")){
            SocketRespone sr = new SocketRespone(0,message1.getRequestId(),"pong");
            wsSession.getWebSocket().send(JSON.toJSONString(sr));
        } else if(StrUtil.equals(message1.getCommand(), Commands.SET_PAGE_MODEL)){
            wsSession.getTerminals().clear();
            PageModel page = jsonObject.getJSONObject("params").to(PageModel.class);
            page.getTerminals().forEach(item->{
                //去重
                if(wsSession.getTerminals().contains(item)){
                    return;
                }
                wsSession.getTerminals().add(item);
            });
            wsSession.getQueries().clear();
            page.getQueries().forEach(item->{
                wsSession.getQueries().put(item.getQueryId(),item.getQueryScript());
            });

            PageMessage pageMessage = new PageMessage();
            //TODO 填充PageModel数据
            pageMessage.setPageId(page.getPageId());
            List<PageMessage.TerminalData> signals = new ArrayList<>();
            pageMessage.setTerminals(signals);
            wsSession.getTerminals().forEach(terminalCode->{
                PageMessage.TerminalData terminal = new PageMessage.TerminalData();
                terminal.setCode(terminalCode);
                terminal.setData(new HashMap<>());
                terminal.setAlarm(new HashMap<>());
                Map<String, Object> statusList = terminalService.getLastValues(terminalCode);
                statusList.forEach((k,v)->{
                    if(v==null)return;
                    terminal.getData().put(k,v);
//                    if(v.isAlarming()){
//                        terminal.getAlarm().put(k,v.getAlarmMsg());
//                    }
                });
                //TODO 处理查询
                signals.add(terminal);
            });
            SocketRespone sr = new SocketRespone(0,message1.getRequestId(),pageMessage);
            wsSession.getWebSocket().send(JSONUtil.toJsonStr(sr));
        }else{
            message1.setParams(jsonObject.getJSONObject("params"));
            EventBus.publish(message1);
        }


    }

    @Override
    public void onOpen(WebSocket socket) {

        WsSession wsSession = new WsSession();
        wsSession.setTerminals(new ArrayList<>());
        wsSession.setQueries(new HashMap<>());
        String token = socket.param("token");
        if(webSocketSet.contains(token)){
            this.remove(token);
        }
        wsSession.setWebSocket(socket);
        webSocketSet.put(token,wsSession);
    }

    @Override
    public void onClose(WebSocket socket) {
        String token = socket.param("token");
        remove(token);
        log.info("[WebSocket] 退出成功，当前连接人数为：={}",webSocketSet.size());
    }
    @Override
    public void onError(WebSocket socket, Throwable error) {
        String token = socket.param("token");
        remove(token);
        error.printStackTrace();
    }

    private void remove(String token){
        WsSession wsSession = webSocketSet.get(token);
        wsSession.getWebSocket().close();
        wsSession.setWebSocket(null);
        wsSession.setQueries(null);
        wsSession.setTerminals(null);
        webSocketSet.remove(token);
    }

    public static void push(String terminalCode, Map<String,Object> data,Map<String,String> alarmInfo){
        webSocketSet.values().forEach(wsSession->{
            if(wsSession.getTerminals().contains(terminalCode)){
                PageMessage pageMessage = new PageMessage();
                List<PageMessage.TerminalData> list = new ArrayList<>();
                PageMessage.TerminalData terminalSignal = new PageMessage.TerminalData();
                terminalSignal.setCode(terminalCode);
                terminalSignal.setData(data);
                terminalSignal.setAlarm(alarmInfo);
                list.add(terminalSignal);
                pageMessage.setTerminals(list);
                SocketRespone sr = new SocketRespone(0,null,pageMessage);
                wsSession.getWebSocket().send(JSON.toJSONString(sr));
            }
        });
    }
}
